/**
 *  @file highScoreModel.cpp
 *
 *  @date 22-dec-2009
 *  @author Ives van der Flaas
 */

#include <sstream>
#include <iostream>
#include "highScoreModel.h"
#include "tinyxml.h"
#include "fileNotFoundException.h"
#include "invalidXMLException.h"


namespace si
{
/**
 * Functor class that will be used by std::sort to sort higscore couples in ascending order.
 */
class HighScoreSorter
{
public:
	bool operator()(std::pair<std::string, int > one, std::pair<std::string, int > two)
	{
		return one.second < two.second;
	}
};

HighScoreModel::HighScoreModel()
{
	// TODO Auto-generated constructor stub

}

HighScoreModel::~HighScoreModel()
{
	// TODO Auto-generated destructor stub
}

bool HighScoreModel::canBeInHighScores(int score)
{
	if(fHighScores.size() < nrOfHighScores)
		return true;

	HighScoreSorter sorter;
	std::sort(fHighScores.begin(), fHighScores.end(), sorter);

	if(score > fHighScores[fHighScores.size()-nrOfHighScores].second)
		return true;
	else
		return false;
}

void HighScoreModel::addEntry(std::string name, int score)
{
	fHighScores.push_back(std::make_pair(name,score));

	HighScoreSorter sorter;
	std::sort(fHighScores.begin(), fHighScores.end(), sorter);

	// Now reverse the order so biggest scores on top
	std::reverse(fHighScores.begin(), fHighScores.end());
}
void HighScoreModel::load()
{
	fHighScores.clear();

	std::string filename = "config/highscores.xml";
	TiXmlDocument scores;
	if(!scores.LoadFile(filename.c_str()))
		return;

	TiXmlNode* versionNode = scores.FirstChild();
	TiXmlDeclaration* versionDecl = versionNode->ToDeclaration();

	if(std::string(versionDecl->Version()) != std::string("1.0"))
		throw InvalidXMLException();

	TiXmlElement* main = scores.FirstChildElement("highscores");

	TiXmlElement* node = main->FirstChildElement();

	while(node != 0)
	{
		std::string name = node->FirstChildElement("name")->GetText();
		std::string scoreStr = node->FirstChildElement("score")->GetText();

		std::stringstream ss;
		ss << scoreStr;
		int score;
		ss >> score;

		fHighScores.push_back(std::make_pair(name, score));
		node = node->NextSiblingElement();
	}

	HighScoreSorter sorter;
	std::sort(fHighScores.begin(), fHighScores.end(), sorter);
	std::reverse(fHighScores.begin(), fHighScores.end());


}


std::pair<std::vector<std::string>, std::vector<int> > HighScoreModel::getVectors() const
{
	std::vector<std::string> names;

	for(unsigned int i = 0; i < fHighScores.size() && (i < nrOfHighScores) ; i++)
		names.push_back(fHighScores[i].first);

	std::vector<int> scores;

	for(unsigned int i = 0; i < fHighScores.size() && (i < nrOfHighScores); i++)
		scores.push_back(fHighScores[i].second);

	return std::make_pair(names, scores);
}
void HighScoreModel::save()
{
	std::string filename = "config/highscores.xml";
	TiXmlDocument scores;

	TiXmlDeclaration* decl = new TiXmlDeclaration("1.0","","");
	scores.LinkEndChild(decl);

	TiXmlElement* highScores = new TiXmlElement("highscores");
	scores.LinkEndChild(highScores);

	for(unsigned int entry = 0; entry < fHighScores.size(); entry++)
	{
		std::pair<std::string, int > p = fHighScores[entry];

		std::string name = fHighScores[entry].first;
		int score = fHighScores[entry].second;
		std::stringstream ss;
		ss << score;
		std::string scoreStr;
		ss >> scoreStr;

		TiXmlElement* anEntry = new TiXmlElement("entry");

		TiXmlElement* nameNode = new TiXmlElement("name");
		TiXmlText* nameText = new TiXmlText(name.c_str());
		nameNode->LinkEndChild(nameText);

		TiXmlElement* scoreNode = new TiXmlElement("score");
		TiXmlText* scoreText = new TiXmlText(scoreStr.c_str());
		scoreNode->LinkEndChild(scoreText);

		anEntry->LinkEndChild(nameNode);
		anEntry->LinkEndChild(scoreNode);

		highScores->LinkEndChild(anEntry);
	}

	scores.SaveFile(filename.c_str());
}

}
